﻿using CSharp.Libs.Media;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using Excel = Microsoft.Office.Interop.Excel; 



namespace Debugging
{
    class Program
    {
        private static DirectoryScanner _dirScan;
        private static Stopwatch _sw;
        private static  int DATA_LINE_POSITION = 12;

        static void Main(string[] args)
        {
            TestManagePictureObjects();
            //TestCreateRemoveTags(); /* Working very well. Can be used to add/delete/update Tag entries */
            //TestCreateNewPictureObject();
            //TestPictureObject();
            //TestRecursiveHashing();
            //TestInts();
        }



        #region Test PictureObject handling
        private static void TestManagePictureObjects()
        {
            PicLib pl = new PicLib();
            pl.Data.DataAccessLayerMessageEvent += Data_DataAccessLayerMessageEvent;

            string strInput = "";
            string[] cmd;
            while (true)
            {
                Console.Clear();
                TestManagePictureObjects_PrintPictureObjects(pl);

                TestManagePictureObjects_PrintMenu();

                strInput = Console.ReadLine();
                cmd = strInput.Split(' ');

                if (cmd[0].ToLower() == "x") { break; }
                else if (cmd[0].ToLower() == "a")
                {
                    PictureObject po = pl.GetPictureObjectByFullFileName(cmd[1]);
                    pl.Data.WritePictureObjectData(po);
                }
                else if (cmd[0].ToLower() == "d")
                {
                    PictureObject po = pl.Data.GetPictureObjectById(cmd[1]);
                    if (po != null)
                    {
                        pl.Data.DeletePictureObject(po);
                    }
                    po = null;
                }
                else if (cmd[0].ToLower() == "spo")
                {
                    PictureObject po = pl.Data.GetPictureObjectById(cmd[1]);
                    if (po != null)
                    {
                        Console.Clear();
                        TestManagePictureObjects_PrintSinglePictureObject(po);
                        Console.Write("Press any key to return to menu");
                        Console.ReadKey();
                    }
                    po = null;
                }
                else if (cmd[0].ToLower() == "lt")
                {
                    Console.Clear();
                    PrintTags(pl);
                    Console.Write("Press any key to return to menu");
                    Console.ReadKey();
                }
                else if (cmd[0].ToLower() == "atpo")
                {
                }
                else if (cmd[0].ToLower() == "dtpo")
                {
                }
            }

            pl.Dispose();
        }

        private static void TestManagePictureObjects_PrintMenu()
        {
            Console.WriteLine("Insert command (Syntax: <Command><Space><Argument>[<Space><Argument>...]):");
            Console.WriteLine("PO=PictureObject TO=TagObject");
            Console.WriteLine("a    - add PO ('a <FullFileName>')");
            Console.WriteLine("d    - delete PO ('d <PictureObjectId>')");
            Console.WriteLine("spo  - show complete PO ('spo <PictureObjectId>')");
            Console.WriteLine("lt   - list Tags ('lt')");
            Console.WriteLine("atpo - add Tag to PO ('atpo <PictureObjectId> <TagId>')");
            Console.WriteLine("dtpo - delete Tag from PO ('dtpo <PictureObjectId> TagId')");
            Console.WriteLine("x    - quit (x for exit ;))");
            Console.Write("Command: ");
        }

        private static void TestManagePictureObjects_PrintPictureObjects(
            PicLib pl)
        {
            //remember cursor position
            int l = Console.CursorLeft;
            int t = Console.CursorTop;

            //set cursor pos
            Console.SetCursorPosition(0, DATA_LINE_POSITION);

            //write list
            List<PictureObject> lstPOs = pl.Data.GetExistingPictureObjects();
            Console.WriteLine("ID\tFile");
            Console.WriteLine("----------------------------------------------------------");
            foreach (PictureObject toPO in lstPOs)
            {
                Console.WriteLine(toPO.PictureObjectId + "\t" + toPO.FullFileName);
            }

            //set cursor back
            Console.SetCursorPosition(l, t);
        }

        private static void TestManagePictureObjects_PrintSinglePictureObject(
            PictureObject po)
        {
            //remember cursor position
            int l = Console.CursorLeft;
            int t = Console.CursorTop;

            //set cursor pos
            Console.SetCursorPosition(0, DATA_LINE_POSITION);

            //write data
            Console.WriteLine("PictureObjectId: " + po.PictureObjectId.ToString());
            Console.WriteLine("BasePathId     : " + po.BasePathId.ToString());
            Console.WriteLine("FullFileName   : " + po.FullFileName);
            Console.WriteLine("FileName       : " + po.FileName);
            Console.WriteLine("Path           : " + po.Path);
            Console.WriteLine("Hash           : " + po.Hash);
            Console.WriteLine("Comment        : " + po.Comment);
            Console.WriteLine("");
            Console.WriteLine("");

            //set cursor back
            Console.SetCursorPosition(l, t);
        }
        #endregion



        #region Test Tag handling
        private static void TestCreateRemoveTags()
        {
            PicLib pl = new PicLib();
            pl.Data.DataAccessLayerMessageEvent += Data_DataAccessLayerMessageEvent;

            string strInput = "";
            string[] cmd;
            while (true)
            {
                Console.Clear();
                PrintTags(pl);

                PrintMenu();

                strInput = Console.ReadLine();
                cmd = strInput.Split(' ');

                if (cmd[0].ToLower() == "x") { break; }
                else if (cmd[0].ToLower() == "a")
                {
                    pl.Data.CreateTag(new TagObject() { Tag = cmd[1] });
                }
                else if (cmd[0].ToLower() == "d")
                {
                    pl.Data.DeleteTag(new TagObject() { TagId = Convert.ToInt32(cmd[1]) });
                }
                else if (cmd[0].ToLower() == "u")
                {
                    pl.Data.UpdateTag(new TagObject() { TagId = Convert.ToInt32(cmd[1]), Tag = cmd[2] });
                }
            }

            pl.Dispose();
        }

        private static void Data_DataAccessLayerMessageEvent(object sender, DataAccessLayerMessageEventArgs ea)
        {
            if (ea.Type == DataAccessLayerMessageType.EntryExists) Console.WriteLine("Tag exists...");
            if (ea.Type == DataAccessLayerMessageType.MultipleEntries) Console.WriteLine("Tag exists multiple times...");
            Console.WriteLine("Message received: " + ea.Message);
            Thread.Sleep(3000);
        }

        private static void PrintTags(
            PicLib pl)
        {
            //remember cursor position
            int l = Console.CursorLeft;
            int t = Console.CursorTop;

            //set cursor pos
            Console.SetCursorPosition(0, DATA_LINE_POSITION);

            //write list
            List<TagObject> lstTags = pl.Data.GetExistingTags();
            Console.WriteLine("TagId\tTag");
            Console.WriteLine("----------------------------------------------------------");
            foreach (TagObject toTag in lstTags)
            {
                Console.WriteLine(toTag.TagId + "\t" + toTag.Tag);
            }

            //set cursor back
            Console.SetCursorPosition(l, t);
        }

        private static void PrintMenu()
        {
            Console.WriteLine("Insert command (Syntax: <Command><Space><Argument>):");
            Console.WriteLine("a - add Tag ('a Test' inserts Tag 'Test')");
            Console.WriteLine("d - delete a Tag ('d 3' deletes Tag with TagId 3)");
            Console.WriteLine("u - update a Tag ('u 4 Testupd' updates TagId 4's Tag to 'Testupd')");
            Console.WriteLine("x - quit (x for exit ;))");
            Console.Write("Command: ");
        }
        #endregion



        #region Test PicLib create a new PictureObject
        private static void TestCreateNewPictureObject()
        {
            PicLib pl = new PicLib();
            PictureObject po = pl.GetPictureObjectByFullFileName(@"d:\download\Hintergrund\DSC_0220.JPG");

            List<TagObject> lTags = pl.Data.GetExistingTags();

            pl.Data.GetPictureObjectData(po);

            po.Tags.Add(new TagObject() { Tag = "Testtag" });
            pl.Data.WritePictureObjectData(po);

            pl.Dispose();
        }
        #endregion



        #region check picture object with and without Constructor
        private static void TestPictureObject()
        {
            Excel.Application xlApp = null;
            Excel.Workbook xlWorkBook = null;
            Excel.Worksheet xlWorkSheet = null;

            OpenExcel(ref xlApp, ref xlWorkBook, ref xlWorkSheet);

            string strInputCount = "";
            string strInputNumberOfObjects = "";

            while (strInputCount.ToLower() != "exit")
            {
                Console.Write("Input count: ");
                strInputCount = Console.ReadLine();
                if (strInputCount.ToLower() == "exit") { break; }
                Console.Write("Input number of objects: ");
                strInputNumberOfObjects = Console.ReadLine();
                int count = 0;
                int numberOfObjects = 0;

                if (int.TryParse(strInputCount, out count) &&
                    int.TryParse(strInputNumberOfObjects, out numberOfObjects))
                {
                    _sw = new Stopwatch();

                    xlWorkSheet.get_Range("A1").Value = "Turncount";
                    xlWorkSheet.get_Range("B1").Value = strInputCount;
                    xlWorkSheet.get_Range("A2").Value = "Number of objects";
                    xlWorkSheet.get_Range("B2").Value = strInputNumberOfObjects;
                    xlWorkSheet.get_Range("A3").Value = "Constructor";
                    xlWorkSheet.get_Range("B3").Value = "No Constructor";

                    //PictureObject WITH constructor
                    for (int i = 1; i <= count; i++)
                    {
                        _sw.Start();
                        for (int j = 1; j <= numberOfObjects; j++)
                        {
                            PictureObject po = new PictureObject();
                        }
                        _sw.Stop();
                        
                        xlWorkSheet.get_Range("A" + (i + 3).ToString()).Value = _sw.ElapsedMilliseconds;

                        _sw.Reset();
                    }

                    //PictureObject WITHOUT constructor
                    for (int i = 1; i <= count; i++)
                    {
                        _sw.Start();
                        for (int j = 1; j <= numberOfObjects; j++)
                        {
                            PictureObjectWithoutConstructor po = new PictureObjectWithoutConstructor();
                        }
                        _sw.Stop();

                        xlWorkSheet.get_Range("B" + (i + 3).ToString()).Value = _sw.ElapsedMilliseconds;

                        _sw.Reset();
                    }

                    Console.WriteLine("Done!");
                }
            }

            CloseExcel(ref xlApp, ref  xlWorkBook, ref  xlWorkSheet);
        }

        private static void OpenExcel(
            ref Excel.Application xlApp,
            ref Excel.Workbook xlWorkBook,
            ref Excel.Worksheet xlWorkSheet)
        {
            string strFileName=@"D:\Results.xlsx";

            object misValue = System.Reflection.Missing.Value;

            xlApp = new Excel.Application();


            if (!File.Exists(strFileName))
            {
                xlWorkBook = (Excel.Workbook)(xlApp.Workbooks.Add(misValue));
                xlWorkBook.SaveAs(strFileName, Excel.XlFileFormat.xlOpenXMLWorkbook);
                xlWorkBook.Close();
            }
            
            xlWorkBook = xlApp.Workbooks.Open(strFileName);
            xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);

            //MessageBox.Show(xlWorkSheet.get_Range("A1", "A1").Value2.ToString());

        }

        private static void CloseExcel(
            ref Excel.Application xlApp,
            ref Excel.Workbook xlWorkBook,
            ref Excel.Worksheet xlWorkSheet)
        {
            xlWorkBook.Close(true);
            xlApp.Quit();

            releaseObject(xlWorkSheet);
            releaseObject(xlWorkBook);
            releaseObject(xlApp);
        }
        
        private static void releaseObject(object obj)
        {
            try
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                obj = null;
            }
            catch (Exception ex)
            {
                obj = null;
                Console.WriteLine("Unable to release the Object " + ex.ToString());
            }
            finally
            {
                GC.Collect();
            }
        }
        #endregion



        #region Test recursive hashing
        private static void TestRecursiveHashing()
        {
            //string strScanDir = @"z:\Bilder";
            string strScanDir = @"d:\LocalSource\TFS";
            //string strScanDir = @"d:\Comos";

            //PicLib pl = new PicLib();
            _dirScan = new DirectoryScanner();
            _sw = new Stopwatch();

            _dirScan.DirectoryScannerProgress += _dirScan_DirectoryScannerProgress;
            _dirScan.AfterCalculatingFileHash += _dirScan_AfterCalculatingFileHash;

            _dirScan.DirectoryToScan = strScanDir;
            Console.WriteLine("Start action");

            _sw.Start();
            //_dirScan.GetFileNamesRecursiveAsync();
            _dirScan.GetAllFileHashesOfDirectoryAsync();

            Console.ReadKey();
        }

        private static void _dirScan_AfterCalculatingFileHash(object sender, CalculatingFileHashEventArgs ea)
        {
            Console.WriteLine("Hash Calculated for '" + ea.FullFileName + "': " + ea.FileHash);
        }

        static void _dirScan_DirectoryScannerProgress(object sender, DirectoryScannerProgressEventArgs ea)
        {
            if (ea.Type == DirectoryScannerProgressTypes.FileCountReceived)
            {
                Console.WriteLine("FileCount received: " + ea.FileCount);
                Console.WriteLine("Took me: " + _sw.Elapsed);
            }
            else if (ea.Type == DirectoryScannerProgressTypes.DirectoryScanFinished)
            {
                _sw.Stop();
                Console.WriteLine("Finished job");
            }
        }
        #endregion



        #region check int's
        private static void TestInts()
        {
            UInt32 i = 111;
            test(i);

            Console.ReadKey();
        }

        private static void test(object param)
        {
            if (param is int) { }
            if (param is Int16) { }
            if (param is Int32) { }
            if (param is Int64) { }
            if (param is UInt16) { }
            if (param is UInt32) { }
            if (param is UInt64) { }
        }
        #endregion
    }
}
